#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QFileDialog"
#include "QDebug"
#include "NestConfigDialog.h"
#include "utils/SVGUtil.hpp"
#include "QPainter"
#include "QGraphicsView"
#include "QGraphicsItem"
#include "QPushButton"
#include <QMessageBox>
#include "algorithm/Nest.h"
#include "NestPathInfoDialog.h"
#include "QThread"
#include "NestPathItem.h"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , nestConfig(new NestConfig())
    , nestConfigDialog(nullptr)
    , nest(nullptr)
    , myNestThread(nullptr)
    , scene(nullptr)
    , algorithm_type(1)
    , selected_size(1)
{
    ui->setupUi(this);
    this->setWindowTitle("easyNest");
    this->setWindowIcon(QIcon(":/image/icon/nest_software.png"));


    this->resize(1300, 1000);
    ui->action_start_nest->setEnabled(false);
    ui->action_save_svg_output->setEnabled(false);
    ui->action_bin_info->setEnabled(false);
    ui->action_stop_nest->setEnabled(false);

    ui->action_import_parts->setIcon(QIcon(":/image/icon/add.png"));
    ui->action_import_bin->setIcon(QIcon(":/image/icon/import.png"));
    ui->action_start_nest->setIcon(QIcon(":/image/icon/start.png"));
    ui->action_stop_nest->setIcon(QIcon(":/image/icon/stop.png"));
    ui->action_save_svg_output->setIcon(QIcon(":/image/icon/fileSave.png"));

    ui->toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    ui->toolBar->setIconSize(QSize(20, 20));
    ui->toolBar->addAction(ui->action_import_parts);
    ui->toolBar->addAction(ui->action_import_bin);
    ui->toolBar->addAction(ui->action_start_nest);
    ui->toolBar->addAction(ui->action_stop_nest);
    ui->toolBar->addAction(ui->action_clean_parts);
    ui->toolBar->addAction(ui->action_zoom_in_output);
    ui->toolBar->addAction(ui->action_zoom_out_output);
    ui->toolBar->addAction(ui->action_save_svg_output);

    connect(ui->action_import_parts, &QAction::triggered, this, &MainWindow::importParts);
    connect(ui->action_import_bin, &QAction::triggered, this,  &MainWindow::importBinPath);
    connect(ui->action_start_nest, &QAction::triggered, this,  &MainWindow::perpareNest);
    connect(ui->action_save_svg_output, &QAction::triggered, this, &MainWindow::saveSVGFile);
    connect(ui->action_bin_info, &QAction::triggered, this,  &MainWindow::openBinInfoDialog );
    connect(ui->action_clean_parts, &QAction::triggered, this, &MainWindow::cleanPathsWindow);
    connect(ui->action_zoom_in_output, &QAction::triggered, this, [=](){ui->nestOutputView->scale(1.1,1.1);});
    connect(ui->action_zoom_out_output, &QAction::triggered, this, [=](){ui->nestOutputView->scale(0.9,0.9);});


    labelStatus = new QLabel("占用率=0.00%,排料裁片数量=0", this);
    labelStatus->setMinimumWidth(150);
    ui->statusbar->addWidget(labelStatus);

    // 裁片窗
    ui->scrollAreaWidgetContents->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
    partsViewLayout = new QHBoxLayout();
    partsViewLayout->setSpacing(10);
    ui->scrollArea->setWidgetResizable(true);
    ui->scrollAreaWidgetContents->setLayout(partsViewLayout);

}

void MainWindow::importParts(){
    QString svgPath =  QFileDialog::getOpenFileName(this,"打开文件","","(*.xml)");
//    QString svgPath = "E://ProgramFiles//QTProjects//build-Nest-Desktop_Qt_5_15_2_MinGW_32_bit-Debug//test_medium.xml";
    if(svgPath == "")
        return;
    cleanPathsWindow();
    this->allPaths = SVGUtil::transferSvgIntoNestPaths(svgPath.toUtf8().data());  //QString转换成char *
    qDebug() << this->allPaths.size();

    // 初始化paths，以及对带孔洞多边形的处理，外围轮廓逆时针，孔洞路径逆时针
    for(int i=0;i<this->allPaths.size();i++){
        this->allPaths[i].id=i+1;
        this->allPaths[i].area = ClipperUtil::areaPolygons(this->allPaths[i]);
        this->allPaths[i].name = "裁片"+std::to_string(i+1);
    }
    this->initPathsWindow();
    this->isEnableNest();
}

void MainWindow::importBinPath(){
    QString svgPath =  QFileDialog::getOpenFileName(this,"打开文件","","(*.xml)");
//    QString svgPath = "E://ProgramFiles//QTProjects//build-Nest-Desktop_Qt_5_15_2_MinGW_32_bit-Debug//big_bin.xml";
//    qDebug()<<svgPath;
    if(svgPath == "")
        return;
    vector<NestPath> paths = SVGUtil::transferSvgIntoNestPaths(svgPath.toUtf8().data());
    qDebug()<< paths.size();
    if(paths.size()!=1){
        qDebug()<<"import bin function goes wrong";
        QMessageBox::critical(this,"底板导入错误","请检查底板文件");
        return;
    }


    this->bin =  paths[0];
    bin.name = "底板";
    bin.id = 0;
    this->isEnableNest();
    ui->action_bin_info->setEnabled(true);
}

//清空partsViewLayout布局内的所有元素
void MainWindow::cleanPathsWindow(){
    QLayoutItem *child;
    while ((child = partsViewLayout->takeAt(0)) != 0)
    {
        //setParent为NULL，防止删除之后界面不消失
        if(child->widget())
        {
            child->widget()->setParent(NULL);
            delete child->widget();//释放
        }
        delete child;
    }
    for(auto& path: allPaths)
        path.selfDelete();
    allPaths.clear();
    ui->action_start_nest->setEnabled(false);
}


void MainWindow::initPathsWindow(){
    for(auto& path:allPaths){
        NestPathItem *item = new NestPathItem(path);
        this->partsViewLayout->addWidget(item);
        connect(item, &NestPathItem::deleteItem,this, &MainWindow::deletePathItem);
    }
}

void MainWindow::deletePathItem(int id){
    for(int i = 0; i < partsViewLayout->count(); i++) {
        QWidget* widget = partsViewLayout->itemAt(i)->widget();

        if(widget) {
            NestPathItem * item = dynamic_cast<NestPathItem*>(widget);
            if(item->m_nestPath.id == id){
                widget->setParent(NULL);
                delete widget;//释放
            }
        }

    }

    allPaths.erase(std::remove_if(allPaths.begin(), allPaths.end(), [=](const NestPath& p) { return p.id == id; }), allPaths.end());
    qDebug()<<allPaths.size();
}

void MainWindow::isEnableNest(){
    if(this->bin.size()!=0&&this->allPaths.size()!=0){
        ui->action_start_nest->setEnabled(true);
    }else{
        ui->action_start_nest->setEnabled(false);
        ui->action_save_svg_output->setEnabled(false);
    }
}


void MainWindow::perpareNest(){
    if(allPaths.empty()){
        QMessageBox::warning(this,"warning","未导入裁片");
        return ;
    }
    if(bin.size() == 0){
        QMessageBox::warning(this,"warning","未导入底板");
        return ;
    }

    if(nestConfigDialog == nullptr){
        this->nestConfigDialog = new NestConfigDialog(this->nestConfig, this);
        connect(nestConfigDialog, &NestConfigDialog::start_nest, this, &MainWindow::startNestThread);
    }

    ui->nestOutputView->resetTransform(); // 恢复缩放

    // 根据底板大小进行缩放
    vector<double> wh = GeometryUtils::getBoundingBoxSize(this->bin);
    int view_w = ui->nestOutputView->width();
    int view_h = ui->nestOutputView->height();
    double m_scale;
    if(wh[0]>wh[1]){
        m_scale = view_h/wh[1]/1.1;
    }else{
        m_scale = view_w/wh[0]/1.1;
    }
    ui->nestOutputView->scale(m_scale,m_scale);
//    ui->nestOutputView->update();
    nestConfigDialog->exec(); // 模态对话框，阻塞
}


void MainWindow::startNestThread(int algo_type){
    qDebug()<<algo_type;
    algorithm_type = algo_type;
    if(this->scene!=nullptr){
        delete this->scene;
        this->scene = nullptr;
    }
    if(algo_type == 1){
        labelStatus->setText("遗传算法排料中...,请稍等");
    }else if(algo_type == 2){
        labelStatus->setText("模拟退火算法排料中...,请稍等");
    }
    myNestThread = new QThread();

    vector<NestPath> selectedPath;
    for(int i = 0; i < partsViewLayout->count(); i++) {
        QWidget* widget = partsViewLayout->itemAt(i)->widget();

        if(widget) {
            NestPathItem * item = dynamic_cast<NestPathItem*>(widget);
            if(item->checkbox->isChecked()){
                selectedPath.push_back(item->m_nestPath);
            }
//            qDebug()<<item->m_nestPath.id;
        }
    }
    selected_size = selectedPath.size();
    this->nest = new Nest(this->bin,selectedPath,*this->nestConfig);
    nest->moveToThread(myNestThread);
    connect(this,&MainWindow::startGANest,this->nest,&Nest::startGANest);
    connect(this,&MainWindow::startSANest,this->nest,&Nest::startSANest);
    qRegisterMetaType<Individual>("Individual&");
    connect(nest,&Nest::drawTemporaryOutput,this,&MainWindow::drawNestOutput);
    connect(nest,&Nest::updateNestState, this, &MainWindow::updateNestState);
    connect(ui->action_stop_nest, &QAction::triggered, [=]{
        nest->stopNest();
        ui->action_stop_nest->setEnabled(false);
    });
    connect(nest,&Nest::nestDone,this,&MainWindow::stopNest);

    myNestThread->start();
    // 不能直接调用线程处理函数，直接调用导致线程处理函数和主线程在同一个线程

    start_time = std::chrono::high_resolution_clock::now();  // 开始计时
    if(algo_type == 1){
        emit startGANest();
    }else if(algo_type == 2){
        emit startSANest();
    }


    ui->action_start_nest->setEnabled(false);
    ui->action_stop_nest->setEnabled(true);
    ui->action_save_svg_output->setEnabled(false);
    ui->action_clean_parts->setEnabled(false);
}

void MainWindow::drawNestOutput(Individual& individual){

    NestPath bin=this->bin;
    std::vector<NestPath> parts=individual.paths;
    std::vector<Vector> placement=individual.placement;
    QGraphicsScene *currentScene = new QGraphicsScene();

////    scene->setSceneRect(0,0,ui->nestOutputView->width(), ui->nestOutputView->height());
    for (int i = 0; i < bin.size(); i++) {
        std::vector<double> x=std::vector<double>();
        std::vector<double> y=std::vector<double>();
        Polygon *polygon=bin[i];
        SVGUtil::buildPolygonVector(polygon,x,y);
        // Convert x,y vectors to a QPolygonF
        QPolygonF poly;
        for (int k = 0; k < x.size(); k++) {
            poly << QPointF(x[k],y[k]);
        }
        // Create a QGraphicsPolygonItem with the polygon shape
        QGraphicsPolygonItem *item = new QGraphicsPolygonItem(poly);
        currentScene->addItem(item);
    }

    for(int i = 0; i < parts.size(); i++){
        NestPath nestPath = parts[i];
        int angle=nestPath.rotation;
        for (int j = 0; j < nestPath.size(); j++) {
            std::vector<double> x=std::vector<double>();
            std::vector<double> y=std::vector<double>();
            Polygon *polygon=GeometryUtils::rotatePolygon(nestPath[j],angle);
            polygon->offset=placement[i];
            SVGUtil::buildPolygonVector(polygon,x,y);

            // Convert x,y vectors to a QPolygonF
            QPolygonF poly;
            for (int k = 0; k < x.size(); k++) {
                poly << QPointF(x[k],y[k]);
            }

            QBrush brush(parts_color);
            // Create a QGraphicsPolygonItem with the polygon shape
            QGraphicsPolygonItem *item = new QGraphicsPolygonItem(poly);
            item->setBrush(brush);
            currentScene->addItem(item);
        }
    }

    QGraphicsScene * previousScene = this->scene;
    this->scene = currentScene;
    delete previousScene;
    ui->nestOutputView->setScene(scene);
}

void MainWindow::updateNestState(double uitilization, int out_count, double currentTemp){
    if(algorithm_type == 1){
        // GA
        labelStatus->setText(QString::asprintf("利用率=%f%，迭代次数=%d，排料裁片数量=%d", uitilization*100, out_count, selected_size));
    }else if(algorithm_type == 2){
        // SA
        labelStatus->setText(QString::asprintf("利用率=%f%，降温次数=%d，当前温度=%f，排料裁片数量=%d", uitilization*100, out_count,currentTemp, selected_size));
    }
}

void MainWindow::stopNest(){
    // 点击了结束或者排料完成
    this->bestIndividual = this->nest->bestIndividual;
    auto end_time = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::seconds>(end_time - start_time).count();
    int hours = static_cast<int>(duration / 3600);
    int mins = static_cast<int>((duration - hours * 3600) / 60);
    int secs = static_cast<int>(duration - hours * 3600 - mins * 60);
    QString timeStr = QString("%1时%2分%3秒").arg(hours, 2, 10, QChar('0'))
                          .arg(mins, 2, 10, QChar('0'))
                          .arg(secs, 2, 10, QChar('0'));

    QMessageBox::information(NULL,  "排料结果",  "排料结束，用时"+timeStr, QMessageBox::Ok);
    ui->action_start_nest->setEnabled(true);
    ui->action_save_svg_output->setEnabled(true);
    ui->action_stop_nest->setEnabled(false);
    ui->action_clean_parts->setEnabled(true);

    if(myNestThread)
    {
        myNestThread->quit();
        myNestThread->wait();
        delete myNestThread;
    }
    if(nest)
    {
        qDebug()<<"nest is exist";
        qDebug()<<nest->config.ALPHA;
        delete nest;
    }
    myNestThread = nullptr;
    nest = nullptr;
    qDebug()<<"all done";
}


void MainWindow::saveSVGFile(){
    //创建一个file文件
    QString fileName =  QFileDialog::getSaveFileName(this,tr("保存文件"),"","html files(*.html);;all files(*.*)");
    qDebug()<<fileName;
    if(fileName == "")
        return;
    string s = SVGUtil::svgGenerator(this->bin, this->bestIndividual);
    SVGUtil::saveSvgFile(s, fileName.toUtf8().data());
    QMessageBox::information(NULL,  "保存结果",  "保存成功", QMessageBox::Ok);

}

void MainWindow::openBinInfoDialog(){
    NestPathInfoDialog *binDialog = new NestPathInfoDialog(&this->bin, this);
    binDialog->setAttribute(Qt::WA_DeleteOnClose);
    binDialog->show();
}



MainWindow::~MainWindow()
{
    if(myNestThread)
    {
        qDebug()<<"删除myThread";
        myNestThread->quit();
        myNestThread->wait();
    }
    qDebug() << "end destroy widget";
    cleanPathsWindow();
    delete ui;

}


